#include "../Logs/nhylog.hpp"

#include <iostream>
#include <vector>
#include <thread>
// c++11 时间特性
#include <chrono>

void bench(const std::string &logger_name, size_t thr_count, size_t msg_count, size_t msg_len)
{
    // 1 获取日志器
    nhylog::Logger::ptr logger = nhylog::getLogger(logger_name);
    if (logger.get() == nullptr)
    {
        // 没这个日志器
        return;
    }

    //
    std::cout << "测试日志：" << msg_count << "条，总大小:" << msg_count * msg_len / 1024 << "kb" << std::endl;

    // 2 组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A'); // 留一个字节给末尾添加换行
    msg.append("/n");
    // 3 创建指定数量线程
    std::vector<std::thread> threads;
    std::vector<double> cost_array(thr_count);

    size_t msg_per_thread = msg_count / thr_count; // 每个线程要输出的日志数量
    for (int i = 0; i < thr_count; i++)
    {
        threads.emplace_back([&, i]{
            // 4 线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();

            // 5 开始循环写日志
            for (int j = 0; j < msg_per_thread; j++)
            {
                logger->fatal("%s", msg.c_str());
            }

            // 6 线程函数内部结束计时

            auto end = std::chrono::high_resolution_clock::now();

            std::chrono::duration<double> cost = end - start;
            cost_array[i] = cost.count();
            std::cout << "thread" << i << ":"
                    << "\t输出日志数量:"
                    << msg_per_thread << "共耗时：" << cost.count() << "s" << std::endl;
        });
    }

    for (int i = 0; i < thr_count; i++)
    {
        threads[i].join();
    }
    // 只计算了写日志用的时间

    // 7 计算总耗时
    // 由于线程是并发的，总时间只是最长的那个线程的
    double max_cost = cost_array[0];
    for (int i = 0; i < thr_count; i++)
    {
        max_cost = std::max(max_cost, cost_array[i]);
    }

    // 每秒输出的数量
    size_t msg_per_sec = msg_count / max_cost;
    // 每秒的输出量
    size_t size_per_sec = (msg_count * msg_len) / (max_cost * 1024);

    // 8 进行输出打印
    std::cout << "每秒输出数量：" << msg_per_sec << "条";
    std::cout << "每秒输出大小：" << size_per_sec << "kb";
    std::cout << std::endl;
}

void sync_bench()
{
    std::unique_ptr<nhylog::LoggerBuider> builder(new nhylog::GlobleLoggerBuider());
    //指挥者的目的是让对象的各个零件按照一定顺序去构造，这里不需要顺序，因此不需要指挥者类
    builder->buildLoggerName("sync_logger");
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(nhylog::LoggerType::LOGGER_SYNC);
    builder->buildSink<nhylog::FileSink>("./logfile/sync.log");
    //builder->buildSink<nhylog::StdoutSink>();
    //builder->buildSink<nhylog::RollBySizeSink>("./logfile/roll-sync-by-size",1024*1024);
    builder->build();

    //bench("sync_logger",1,1000000,100);

    bench("sync_logger",3,1000000,100);
}

void async_bench()
{
        std::unique_ptr<nhylog::LoggerBuider> builder(new nhylog::GlobleLoggerBuider());
    //指挥者的目的是让对象的各个零件按照一定顺序去构造，这里不需要顺序，因此不需要指挥者类
    builder->buildLoggerName("async_logger");
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(nhylog::LoggerType::LOGGER_ASYNC);
    builder->buildEnableUnSafeAsync();
    builder->buildSink<nhylog::FileSink>("./logfile/sync.log");
    builder->build();

    bench("async_logger",1,1000000,100);

}

int main()
{
    async_bench();
    return 0;
}
